package com.duoqin.account;

import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;

import com.duoqin.account.data.LoginResponse;

public class DuoqinAccount {
    private static final String TAG = "duoqin";

    public static final String DUOQIN_ACCOUNT_TYPE = "com.duoqin.android.account";
    public static final String DUOQIN_ACCOUNT_TOKEN_TYPE = "full_access";
    public static final String DUOQIN_ACCOUNT_UID = "uid";
    public static final String DUOQIN_ACCOUNT_TOKEN_EXPIREDAT = "expiredAt";

    public static final String INTENT_ACTION_LOGIN = "com.duoqin.account.Login";
    public static final String INTENT_ACTION_REGISTER = "com.duoqin.account.Register";
    public static final String INTENT_ACTION_ACCOUNT_UPDATE = "com.duoqin.account.update";

    public static final int LOGIN_STATE_SUCCESS = 0;
    public static final int LOGIN_STATE_NO_ACCOUNT = -1;
    public static final int LOGIN_STATE_TOKEN_EXPIRED = -2;
    public static final int LOGIN_STATE_NOT_LOGIN = -3;

    public static void addAccount(Context context, String accountName, String password,
                                  LoginResponse.DataBean data) {
        if (TextUtils.isEmpty(accountName)) return;
        Account account = new Account(accountName, DuoqinAccount.DUOQIN_ACCOUNT_TYPE);

        AccountManager am = AccountManager.get(context);
        am.addAccountExplicitly(account, password, null);
        if (data != null) {
            am.setUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_UID, data.getUid());
            am.setUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_TYPE, data.getAccessToken());
            am.setUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_EXPIREDAT,
                    data.getExpiredAt()+"");
        }
        Log.i(TAG, "addAccount");
        Intent intent = new Intent(DuoqinAccount.INTENT_ACTION_ACCOUNT_UPDATE);
        intent.setPackage("com.duoqin.remoteservice");
        context.sendBroadcast(intent);
    }

    public static String getAccountToken(Context context) {
        String token = null;
        AccountManager am = AccountManager.get(context);
        Account account = getAccount(context);
        if (account != null) {
            token = am.getUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_TYPE);
        }
        Log.d(TAG, "getAccountToken = " + token);
        return token;
    }

    public static boolean isAccountTokenExpired(Context context) {
        boolean expired = true;
        AccountManager am = AccountManager.get(context);
        Account account = getAccount(context);
        if (account != null) {
            String expiredAt = am.getUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_EXPIREDAT);
            if (expiredAt != null) {
                try {
                    long expiredTimeStamp = Long.valueOf(expiredAt);
                    if (expiredTimeStamp > System.currentTimeMillis()) {
                        expired = false;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        Log.d(TAG, "isAccountTokenExpired = " + expired);
        return expired;
    }

    // Token and ExpiredAt must be updated together
    public static void updateAccountToken(Context context, String token, long expiredAt) {
        AccountManager am = AccountManager.get(context);
        Account account = getAccount(context);
        if (account != null) {
            Log.d(TAG, "updateAccountToken = " + token);
            am.setUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_TYPE, token);
            am.setUserData(account, DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_EXPIREDAT, expiredAt + "");
        }
    }

    public static void removeAllAccounts(Context context) {
        AccountManager accountManager = AccountManager.get(context);
        Account[] accounts = accountManager.getAccountsByType(DUOQIN_ACCOUNT_TYPE);
        if(accounts.length > 0) {
            for (Account account : accounts) {
                try {
                    accountManager.removeAccount(account, null, null);
                }catch (Throwable e){
                    e.printStackTrace();
                }
            }
            // broadcast account logout
            Log.i(TAG, "removeAllAccounts");
            Intent intent = new Intent(DuoqinAccount.INTENT_ACTION_ACCOUNT_UPDATE);
            intent.setPackage("com.duoqin.remoteservice");
            context.sendBroadcast(intent);
        }
    }

    public static boolean removeAccount(Context context, String userName){
        try {
            if (!TextUtils.isEmpty(userName)) {
                AccountManager accountManager = AccountManager.get(context);
                accountManager.removeAccount(new Account(userName, DUOQIN_ACCOUNT_TYPE), null, null);
                // broadcast account logout
                Log.i(TAG, "removeAccount " + userName);
                Intent intent = new Intent(DuoqinAccount.INTENT_ACTION_ACCOUNT_UPDATE);
                intent.setPackage("com.duoqin.remoteservice");
                context.sendBroadcast(intent);
                return true;
            }
        }catch (Throwable e) {
            e.printStackTrace();
        }
        return false;
    }

    public static Account getAccount(Context context) {
        if (checkAccountPermission(context)) {
            final Account[] accounts = AccountManager.get(context).
                    getAccountsByType(DUOQIN_ACCOUNT_TYPE);
            if (accounts.length > 0) {
                Log.d(TAG, "getAccount = " + accounts[0].name);
                return accounts[0];
            }
        }
        return null;
    }

    public static String getAccountName(Context context) {
        String accountName = null;
        if (checkAccountPermission(context)) {
            final Account[] accounts = AccountManager.get(context).
                    getAccountsByType(DUOQIN_ACCOUNT_TYPE);
            if (accounts.length > 0) {
                accountName = accounts[0].name;
            }
        }
        Log.d(TAG, "getAccountName = " + accountName);
        return accountName;
    }

    private static boolean checkAccountPermission(Context context) {
        Log.e("GET_ACCOUNTS",ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS) + "");
        return ContextCompat.checkSelfPermission(context, Manifest.permission.GET_ACCOUNTS)
                == PackageManager.PERMISSION_GRANTED;
    }

    public static int getLoginState(Context context){
        int state = LOGIN_STATE_NO_ACCOUNT;
        try {
            AccountManager accountManager = AccountManager.get(context);
            Account[] accounts = accountManager.getAccountsByType(DUOQIN_ACCOUNT_TYPE);
            for(Account account : accounts) {
                if (account.name != null) {
                    state = LOGIN_STATE_NOT_LOGIN;
                    String token = accountManager.getUserData(account, DUOQIN_ACCOUNT_TOKEN_TYPE);
                    if (!TextUtils.isEmpty(token)) {
                        state = LOGIN_STATE_TOKEN_EXPIRED;
                        String expiredAtStr = accountManager.getUserData(account,
                                DUOQIN_ACCOUNT_TOKEN_EXPIREDAT);
                        long expiredAt = Long.valueOf(expiredAtStr);
                        if (expiredAt > System.currentTimeMillis()) {
                            state = LOGIN_STATE_SUCCESS;
                            break;
                        } else {
                            Log.i(TAG, "token expiredAt = " + expiredAt
                                    + "; SystemTime = " + System.currentTimeMillis());
                            // Clear token and expiredAt together
                            accountManager.setUserData(account,
                                    DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_TYPE, null);
                            accountManager.setUserData(account,
                                    DuoqinAccount.DUOQIN_ACCOUNT_TOKEN_EXPIREDAT, "-1");
                        }
                    }
                }
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        Log.d(TAG, "getLoginState = " + state);
        return state;
    }


}
